home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Textfiles / HackintoshBiblev1.3.sit / Hackintosh Bible v1.3.rsrc / styl_151.rtf < prev    next >
Text File  |  1996-11-10  |  36KB  |  4 lines

  1. {\rtf1\ansi
  2. {\fonttbl\f0\fswiss Courier;}
  3. {\colortbl\red255\green2\blue0;}
  4. \f0\b0\i0\outl0\shad0\fs20 \cf0 \expan0 \ul0 `Beta Notes: 10/17/91\line \line The following bold entries constitute a tentative outline for topics to dicuss in detail.  Some of these topics will require a fair amount of research on my part - in particular, the Eve and Encryption sections will take some time.  After this section come the live cracks.  These represent an attempt to take a novice cracker through every step of the cracking process detailing choices and decisions that I would make as I go and why I would make them.\line \line Any feedback would be greatly appreciated - especially from any novice crackers who find parts of this document incomprehensible.  Note that this is a rough draft - there are bound to be errors although hopefully no logical ones (just syntactical and/or spelling).\line \line Determining where to start looking\line \line 1) Types of protection\line  a) Serial number schemes\line  b) Registration codes\line  c) Network serial checks [AppleTalk driver stuff]\line  d) Hardware plugs - see below\line  e) Encryption - see below\line  f) Time stamps\line  g) Key disk\line \line How to break into programs\line \line 1) Trap interrupts\line  a) Dialog/Alert traps\line  b) MenuSelect\line  c) InitFonts etc.\line 2) Manual entrance of TMON [Good luck]\line 3) Automatic TMON entrance via code modification [_Debugger trap insertion]\line  a) Determining an address with Nosy\line  b) Determining an address from the Jump Table\line  c) \line \line Using TMON, Nosy, and ResEdit together\line \line 1) Determining address offsets\line 2) Nosy vs TMON\line  a) Why Nosy "feels better"\line  b) Why TMON is virtually omniscient\line \line TMON Tricks\line \line 1) TMON tricks with register values, flags, and instruction modification\line 2) One step ModalDialog hassles [Serial number schemes]\line 3) TMON Pro shortcuts\line \line Determining the type of crack to apply\line \line 1) Bypasses vs cracks\line 2) Finding the key code\line 3) Branch switching\line  a) Mention something about branch op-codes - 2 and 4 byte instructions and offsets\line 4) Flag/variable modification\line 5) Code modification\line \line Everything you always wanted to know about the CODE 0 Jump Table.\line \line 1) What it is and how it works\line 2) Locating an entry point\line 3) Modifications\line \line Hardware plugs\line \line 1) General tips [Device Manager stuff]\line 2) Eve bullshit\line \line Encrypted Code\line \line Unless you are one hell of a genius at cryptology and have lots of time to kill, the encrypted CODE resources will have to be de-crypted and written back to the program.  Here is why:  to decrypt itself, a program will usually either take a known seed number and use it on each encrypted byte of the code or else it will start with some byte in the code and do a forward decrypt,  i.e. the first byte decrypts the second byte, the new second byte decrypts the third byte, and so on.  A simple method might be to have some code that looks like this:\line \line  MOVE\line #1000,D0\line  LEA\line encryptedshit,A0\line  LEA\line encryptedshit-1,A1\line loop1\line EOR.L\line (A1)+,(A0)+\line  DBRA\line D0,loop1\line encryptedshit\line Here is where the encrypted gibberish begins.\line \line This is a simple example, but note how it functions.  D0 gets the number of longwords to decrypt, A0 is the destination (where the decrypted stuff will go - which is right back over the encrypted stuff) and A1 gets the decrypting key which is the long word that was previously decrypted.  Then the code simply loops D0 times writing over the encrypted code with the decrypted code.  After this code has finished, the program continues execution right where the encrypted (and now decrypted) code begins.  Now cosider: somewhere in the encrypted stuff is the error check that you have to modify.  This will be simple enough to locate assuming that you can run the decryption routine and then immediately regain control in TMON.  The problem is that when you go to modify the error check so that it always passes, the modification screws up the decryption routine.  This is because the decryption routine requires the exact original values to run properly since these values are the keys that the code uses.  So a crack using traditional methods requires that you not only change the error branch, but that you also change every other encrypted value such that the decryption routine still runs properly - no small feat!\line \line A much more feasable method would be to decrypt the code, make the necessary modifications to the error routine, and then disable the decryption routine (just branching around it would do) and writing the whole mess (un-encrypted) back to the original code resource.\line \line So much for the theory, now if I could just crack one of these suckers...\line \line \line Live Cracks\line \line \line MultiClip 2.0\line \line This program uses a network checking algorithm to determine whether multiple copies with the same serial number are currently running - if you don't use this program on a network, you will never see the error.\line \line Step 1:  Where to start looking.\line \line There are actually several good places to begin looking for the protection (especially if you have already cracked it - but I will assume that you have not).  First of all, since the program scans the network, it is probably using the _Open Trap somewhere early in its code to to access the Appletalk driver.  Second, it displays an error dialog (or alert) so we could open it up in Resedit, find the error dialog (and note its ID # for later use) and then Nosy it and look at procedures that call ModalDialog or one of the Alert traps to try and find the one that displays the dialog with the proper ID #.  Third, we could have TMON trap either 1) ModalDialog if it is a dialog or 2) StopAlert, CautionAlert or NoteAlert if it is an Alert and begin tracing from that point backwords.  Fourth, we could just Nosy it and start from the top (the slow way).\line \line Whenever a program displays an error dialog (not a serial number dialog which seems to be in vogue these days) I almost always find the ID # of the dialog or alert and begin looking at procs in Nosy, so let's start there.  In Resedit, we note that it is Dialog (and not Alert) #128 that is the problem.  On to Nosy.  After Nosy analyzes the INIT resource, open up the Trap Refs List under the Display menu and scroll down to GetNewDialog.  Here you will find two listings: ASKNAME and PUTREGISTERDLOG.  Since there are only two we can quickly check them both out (if there were a bunch, I would probably try a different method).  First let us look at ASKNAME -  here is the listing down to the GetNewDialog:\line \line    42BA:                                 QUAL    ASKNAME ; b# =184  s#1  =proc54\line \line                                  vdu_1     VEQU  -26\line                                  vdu_2     VEQU  -18\line                                  vdu_3     VEQU  -12\line                                  vdu_4     VEQU  -10\line                                  vdu_5     VEQU  -8\line                                  param1    VEQU  8\line                                  funRslt   VEQU  12\line     42BA:                                 VEND    \line \line                                ;-refs - com_43    MYFILTERFORNAME  \line \line     42BA: 4E56 FFE6      'NV..'  ASKNAME  LINK    A6,#-$1A\line     42BE: 48E7 0318      'H...'           MOVEM.L D6-D7/A3-A4,-(A7)\line     42C2: 2C2E 0008      2000008          MOVE.L  param1(A6),D6\line     42C6: 42A7           'B.'             CLR.L   -(A7)\line     42C8: 4EBA E642      100290C          JSR     proc19\line     42CC: 285F           '(_'             POP.L   A4\line     42CE: 486E FFF8      200FFF8          PEA     vdu_5(A6)\line     42D2: A874           '.t'             _GetPort ; (VAR port:GrafPtr) \line     42D4: 42A7           'B.'             CLR.L   -(A7)\line     42D6: 302C 001E      '0,..'           MOVE    30(A4),D0\line     42DA: D07C 0014      '.|..'           ADD     #20,D0\line     42DE: 3F00           '?.'             PUSH    D0\line     42E0: 42A7           'B.'             CLR.L   -(A7)\line     42E2: 70FF           'p.'             MOVEQ   #-1,D0\line     42E4: 2F00           '/.'             PUSH.L  D0\line     42E6: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr; behind:WindowPtr):DialogPtr \line \line The first thing to do is to locate the _GetNewDialog and determine its associated parameters: actually all we care about is the first parameter, the ID #.  Tracing backwords, we see that -1 is the third parm, 0 is the second parm, and 30(A4) + #20 (from the ADD #20,D0) is the first parm.  Well, we have a problem here.  Instead of a nice plain ID # being passed to GetNewDialog, the ID # is hidden on the stack frame somewhere.  At this point it is best to mark this proc as indeterminite and go on to the next one.  If we must come back to this one then we will have to figure out if ID #128 is valid for this proc and go from there.  So let us look at PUTREGISTERDLOG\line \line   33AC:                                 QUAL    PUTREGISTERDLOG ; b# =141  s#1  =proc35\line \line                                vdb_1     VEQU  -286\line                                vdb_2     VEQU  -278\line                                vdb_3     VEQU  -276\line                                vdb_4     VEQU  -274\line                                vdb_5     VEQU  -272\line                                vdb_6     VEQU  -270\line                                vdb_7     VEQU  -268\line                                vdb_8     VEQU  -264\line                                vdb_9     VEQU  -262\line                                vdb_10    VEQU  -256\line                                param1    VEQU  8\line   33AC:                                 VEND    \line \line                                ;-refs - INIT1     \line \line                                PUTREGISTERDLOG\line   33AC: 4E56 FEE2      'NV..'           LINK    A6,#-$11E\line   33B0: 2F0C           '/.'             PUSH.L  A4\line   33B2: 206E 0008      2000008          MOVEA.L param1(A6),A0\line   33B6: 43EE FF00      200FF00          LEA     vdb_10(A6),A1\line   33BA: 703F           'p?'             MOVEQ   #63,D0\line   33BC: 22D8           '".'    ldb_1    MOVE.L  (A0)+,(A1)+\line   33BE: 51C8 FFFC      10033BC          DBRA    D0,ldb_1\line   33C2: 42A7           'B.'             CLR.L   -(A7)\line   33C4: 3F3C 0080      '?<..'           PUSH    #128\line   33C8: 42A7           'B.'             CLR.L   -(A7)\line   33CA: 70FF           'p.'             MOVEQ   #-1,D0\line   33CC: 2F00           '/.'             PUSH.L  D0\line   33CE: A97C           '.|'             _GetNewDialog ; (DlgID:INTEGER; wStorage:Ptr; behind:WindowPtr):DialogPtr \line \line \line Once again, find the GetNewDialog and determine the parms.  Here we have -1 for the third, 0 for the second, and lo and behold, 128 for the first.  This is definately our procedure.  Note that this is an extremely easy example as no attempt has been made to disguise the ID # - it is clearly 128, the value we have been looking for all along.\line \line Determining how to implement the crack.\line \line  The obvious place to start looking is just before the error dialog has been loaded.  Here is that section of code from the above procedure:\line \line LINK    A6,#-$11E\line PUSH.L  A4\line MOVEA.L param1(A6),A0\line LEA     vdb_10(A6),A1\line MOVEQ   #63,D0\line ldb 1\line MOVE.L  (A0)+,(A1)+\line DBRA    D0,ldb_1\line  Next comes the code we just looked at\line CLR.L   -(A7)\line PUSH    #128\line CLR.L   -(A7)\line MOVEQ   #-1,D0\line PUSH.L  D0\line _GetNewDialog\line \line As we look at this code, keep in mind what it is that we are looking for.  We know that the program is capable of loading without this error, so somewhere it has to be checking the network and then either branching to the error code (if it detects a copy of itself) or else branching around the error code.  So we need to find the branch that is causing this segment of code to execute.  A quick scan of the code that precedes the error dialog code should reveal nothing of interest.  A Link followed by a 63 word Move Loop - no branches of any consequence whatsoever.  If you are wondering why we can immediately eliminate the DBRA  D0,ldb1 (after all, it is a branch) then ask yourself this:  1st, where does the branch go? Answer: to the line above the branch instruction.  2nd, what (if any) conditions is it checking? Answer: it checks to see if D0 (an obvious loop counter in this case) is equal to zero.  If the branch does not either 1) branch directly to the error code (in this case it would have to be branching to the CLR.L -(A7) ) or 2) branch around the error code (somewhere after the GetNewDialog and the ensuing ModalDialog and probably even an ensuing DisposeDialog) then the branch is almost certainly a bad candidate.  You particulaly should be able to immediately eliminate loop terminator branches like the one above.\line \line Well, since we have eliminated the only branch in this procedure above the GetNewDialog, we will have to look elsewhere.  The next obvious place to look is in the procedure that called this one.  Again Nosy makes this a snap.  Take a look at the line right above the code listing that read refs - INIT1.  The refs line tells you every procedure that calls the one you are currently looking at.  Luckily, there is only one, so let us look at it next.  Since this is a long procedure, I am only listing the section that surrounds the JSR PUTREGISTERDLOG line.  I should also mention that I am writing this with a copy that I cracked a while ago and in un-cracking it for this document, could not remember exactly what the changed code was.  I will show you where your code listing might differ from mine below:\line \line    196: 4268 0004      'Bh..'           CLR     4(A0)\line    19A: 4228 0006      'B(..'           CLR.B   6(A0)\line    19E: 4228 0007      'B(..'           CLR.B   7(A0)\line    1A2: 43FA 036E      1000512          LEA     data2,A1    ; len= 1\line    1A6: 45E8 0009      'E...'           LEA     9(A0),A2\line    1AA: 4EBA 0392      100053E          JSR     proc2\line    1AE: 43FA 03A2      1000552          LEA     data4,A1    ; 'Multi'\line    1B2: 4EBA 038A      100053E          JSR     proc2\line    1B6: 43FA 03AC      1000564          LEA     data7,A1    ; len= 2\line    1BA: 4EBA 0382      100053E          JSR     proc2\line    1BE: 4A6E FFEC      200FFEC          TST     vab_2(A6)\line    1C2: 6756           100021A          BEQ.S   lab_13\line    1C4: 4FEF FFFE      'O...'           LEA     -2(A7),A7\line    1C8: 2F2E FFEE      200FFEE          PUSH.L  vab_3(A6)\line    1CC: 4EBA 2C88      1002E56          JSR     proc29\line    1D0: 301F           '0.'             POP     D0\line    1D2: 6646           100021A          BNE.S   lab_13\line    1D4: 4FEF FFCE      'O...'           LEA     -50(A7),A7\line    1D8: 204F           ' O'             MOVEA.L A7,A0\line    1DA: 317C FFF6 0018 '1|....'         MOVE    #$FFF6,ioCRefNum(A0)\line    1E0: 216E FFEE 001E 200FFEE          MOVE.L  vab_3(A6),ioSEBlkPtr(A0)\line    1E6: 317C 00FC 001A '1|....'         MOVE    #252,CSCode(A0)\line    1EC: A004           '..'             _Control ; (A0|IOPB:ParamBlockRec):D0\\OSErr \line    1EE: 4FEF 0032      'O..2'           LEA     50(A7),A7\line    1F2: 206E FFEE      200FFEE          MOVEA.L vab_3(A6),A0\line    1F6: A01F           '..'             _DisposPtr ; (A0/p:Ptr) \line    1F8: 486D FFFC           -4          PEA     glob1(A5)\line    1FC: A86E           '.n'             _InitGraf ; (globalPtr:Ptr) \line    1FE: A8FE           '..'             _InitFonts  \line    200: A912           '..'             _InitWindows  \line    202: A9CC           '..'             _TeInit  \line    204: 42A7           'B.'             CLR.L   -(A7)\line    206: A97B           '.{'             _InitDialogs ; (resumeProc:ProcPtr) \line    208: A850           '.P'             _InitCursor  \line    20A: 42B8 0A6C         $A6C          CLR.L   DeskHook\line    20E: 487A 0302      1000512          PEA     data2       ; len= 1\line    212: 4EBA 3198      10033AC          JSR     PUTREGISTERDLOG\line    216: 4EFA 0316      100052E          JMP     com_2\line    21A: 4227           'B''    lab_13   CLR.B   -(A7)\line    21C: A99B           '..'             _SetResLoad ; (AutoLoad:BOOLEAN) \line    21E: 42A7           'B.'             CLR.L   -(A7)\line    220: 2F3C 4452 5652 '/<DRVR'         PUSH.L  #'DRVR'\line    226: 487A 2156      100237E          PEA     data35      ; len= 12\line    22A: A9A1           '..'             _GetNamedResource ; (theType:ResType; name:Str255):Handle \line    22C: 1F3C 0001      '.<..'           PUSH.B  #1\line    230: A99B           '..'             _SetResLoad ; (AutoLoad:BOOLEAN) \line   \line First off, we need to find the line that calls the error procedure we just finished looking at.  In this case the line will be either JSR PUTREGISTERDLOG or BSR PURREGISTERDLOG.  We find the correct line just above lab 13.  Now, quickly note the structure we are dealing with: we have JSR PUTREGISTERDLOG (which does all the error dialog stuff) followed by a JMP instruction.  So the program is leaving the main flow of control after doing the error dialog.  This is important because we can see that logically, there should be a branch that skips this piece of code and continues on with lab 13.  If we scan backwords from the JSR PUT... we see a bunch of Initialization traps preceded by some Moves - but then notice this code:\line \line JSR     proc2\line TST     vab_2(A6)\line BEQ.S   lab_13\line LEA     -2(A7),A7\line PUSH.L  vab_3(A6)\line JSR     proc29\line POP     D0\line BNE.S   lab_13\line \line Here is where I forget what the original code looked like so your listing might say BEQ.S lab 13 (for the second branch that is).  Anyways, this code looks really good since it branches around the error section.  At this point, we might hazard a guess and simply make these Branch instructions always execute by changing them to BRA lab 13.  This might be an incorrect crack since the program could be making other checks above this code - we can eliminate this chance by continuing scanning upwards looking for references to lab 13 until the beginning of this procedure.  What I would do in a case like this is make a real fast check of about 50 or so lines of code above this looking for branches refering to lab 13.  If I find one, modify it...if not, then make the crack and test it.  If the crack fails, then I would know to keep looking.\line \line A quick note:  The flow of the program seems to suggest that merely changing the first branch from BEQ to BRA would suffice since this instruction always executes (it is not branched around anywhere) and once this instruction branches to lab 13 there would be no need to change the second branch.  However, I am writing this having already cracked this program and the method I used was to change the second branch only.  Since I know that this works and cannot test any other method (not having a network at my disposal), I will proceed in this manner.  The would-be cracker could certainly try changing the first branch and it looks to me as if this would work.\line \line So how is the crack applied?  Well, in this case, it looks like the program branches to lab 13 only if the serial check is OK (i.e. there are no extra copies running on the network) so we need to to make this branch always execute.  The easiest way to do this is to change the BNE.S lab 13 to BRA.S lab 13 - branch not equal turns into branch always.  So, simply pop over to Resedit and open the proper resource (INIT in this case).  To determine the ID of the resource, look at the top of the procedure window in Nosy.  The first line will contain an s# followed by a number.  This is the segment number or ID # of the resource (in this case it is obvious since there is only one INIT resource, but for CODE resources this is really handy).  Once the resource is open (make sure you do not have the Resedit disassembler running - if you do, select Open Using Hex Editor from the Resource menu) scan down to the line that most closely matches the line you want to modify - in this case our line is 1D2 so find line 1D0 in Resedit and look over 2 bytes.  There should be the code 6646.  Just click in front of the 66, backspace to delete it,  and type 60 (You can find these op-code numbers in the Cracker's Guide Part 1).  Now quit and save changes and the crack is complete.\line \line Infini-d 1.1\line \line This program uses the common serial number / personalize dialog scheme.\line \line Step 1:  Where to start looking.\line \line We have two good options here: 1) Find the Dialog ID # in Resedit and use Nosy's Trap Refs List or 2) trap ModalDialog in TMON and start tracing from there.  I tend to use the second method, usually because I can implement the crack on the fly in TMON and actually run the program.  Then I go back later and figure out how do a full crack with Nosy.  Note that withe the second method we do not have to go through every stupid dialog in the program.  Rather we can simply find the unfriendly ModalDialog and let TMON tell us which code resource we are in.\line \line First, drop into TMON and set a trap intercept for _ModalDialog then exit TMON and launch Infini-D.  TMON will proceed to stop execution at the first ModalDialog trap.  Since it is possible for a program to have ModalDialog traps before the one that actually does the serial number stuff my first step is to immediately exit TMON and keep track of how many ModalDialogs occur before the serial number dialog comes up.  In this case it is the first ModalDialog, so I would have to then quit and start over, this time not exiting TMON when the trap occurs.\line \line Once you are in TMON, open an Assembly window to (PC) to look at the code that is executing.  I forget exactly, but essentially what you would see is the ModalDialog trap followed by a couple of meaningless instructions and an RTS.  Since nothing happens after the ModalDialog, we would need to Step through the RTS to get back to the procedure that called this one.\line \line I should make a quick note here:  this technique of making an on the fly crack via TMON usually means that you are going to ruin the application, i.e. you are going to end up with a serialized program that no longer needs to be cracked.  This is not a true crack, rather this is a bypass - once this is done, the program is personalized and ready to run; in a sense you are letting the program crack itself.  If you wanted to make a true cracked copy, you would have to look at exactly which branches were modified in TMON and then go into Resedit and change the same instructions (with an un-serialized copy of the application).\line \line OK, enough about that.  Here is the code you would see:\line \line PEA\line   $157A(A5)\line MOVE.L  $000C(A6),-(A7)\line _ModalDialog\line UNLK\line   A6\line RTS\line \line Since the procedure ends right after the ModalDialog call, we need to step through the RTS to see what called this procedure...and here is that code:\line \line 001E50B4: LINK.W    A6,#$FFFE\line 001E50B8: PEA\line   `FFFE(A6)\line 001E50BC: CLR.L\line   -(A7)\line 001E50BE: JSR\line   $1572(A5)\line 001E50C2: ADDQ.L    #8,A7\line 001E50C4: CMPI.W    #$0001,`FFFE(A6)\line 001E50CA: BEQ.S\line   ^$001E50D8\line  \line 001E50CC: CMPI.W\line   #$0002,`FFFE(A6)\line 001E50D2: BEQ.S\line   ^$001E50D8\line  \line 001E50D4: MOVEQ\line   #$00,D0\line 001E50D6: BRA.S\line   ^$001E50DA\line  \line 001E50D8: MOVEQ\line   #$01,D0\line 001E50DA: TST.W\line   D0\line 001E50DC: BEQ.S\line   ^$001E50B8\line  \line 001E50DE: CMPI.W    #$0001,`FFFE(A6)\line 001E50E4: BNE.S\line   ^$001E50EA\line  \line 001E50E6: MOVEQ\line   #$01,D0\line 001E50E8: BRA.S\line   ^$001E50EC\line  \line 001E50EA: MOVEQ\line   #$00,D0\line 001E50EC: UNLK\line   A6\line 001E50EE: RTS\line \line Well, there is quite a bit of comparing and branching going on here so we had better see if we can figure out what is happening.  After the Link, the dialog handle is pushed on the stack, space for a return value (or maybe a parameter with value 0) is put on the stack and then the ModalDialog procedure is called.  This is pretty standard.  Next, the stack is restored to its original value and something is compared to 1, branch if so, then compare the same thing to 2 and branch if so.  Notice an important thing here, namely that this procedure never calls GetDItem or GetIText nor does it call any more subroutines so this procedure cannot be the one that checks the serial number.  So it is probably a safe bet that this procedure is testing to see what exactly the user did - hit OK? hit Cancel? Type in a keystroke?  Assuming for the moment that this is the case, take a wild guess what the various dialog item numbers are?  You guessed it...1 is the OK button, 2 is the Cancel button.  Now look at the code and you can quickly see what is happening (still assuming our item number theory is correct).  First, if the item number hit was one (OK button) then branch down, and put a 1 in D0.  If the item number hit was 2 (Cancel button) then do the same thing.  Otherwise put a zero in D0.  Finally, TST D0 and if it was 0 (neither button hit) then loop back and call ModalDialog again.  At this point the program knows one of the buttons was hit.  So, if it was not the OK button, branch down and put 0 in D0 otherwise put a 1 in D0 (so that's Cancel = 0, OK = 1).  When we look at the procedure that called this one, we know that D0 will tell that procedure what happened (either OK or Cancel).\line \line Note that this is one of those problem ModalDialog calls that exits everytime you hit a keystroke so you cannot just type in your name and serial number, hit OK to get back to TMON, and crack the sucker.  Rather you have to either 1) settle for only typing in one letter before you crack it or 2) set a breakpoint just past the part were it tests for the OK button being hit, clear the ModalDialog trace, and exit - TMON won't interrupt until you hit the OK button and the breakpoint is encountered.\line \line Finally, here is the last piece of code - the procedure that called the above procedure:\line \line 001E4FBE: ADDQ.L  #6,A7\line 001E4FC0:JSR\line ^$001E50B4\line \line 001E4FC4: MOVE.W  D0,`FFFE(A6)\line  Here is where we returned from the above procedure. 1 = OK, 0 = Cancel\line 001E4FC8: CMPI.W  #$0001,`FFFE(A6)\line 001E4FCE:BNE.S\line ^$001E5012\line  Branch if Cancel hit\line 001E4FD0:PEA\line `FEF8(A6)\line 001E4FD4: MOVE.W  #$000A,-(A7)\line 001E4FD8:JSR\line ^$001E4F58\line \line 001E4FDC: ADDQ.L  #6,A7\line  \line 001E4FDE:PEA\line `FEF8(A6)\line 001E4FE2:JSR\line ^$001E52AC\line \line 001E4FE6: ADDQ.L  #4,A7\line 001E4FE8: MOVE.W  D0,`FFFC(A6)\line 001E4FEC:TST.W\line `FFFC(A6)\line 001E4FF0:BNE.S\line ^$001E5012\line \line 001E4FF2: MOVE.W  #$0001,-(A7)\line 001E4FF6:CLR.W\line -(A7)\line 001E4FF8: MOVE.W \line  #$0034,-(A7)\line 001E4FFC:JSR\line $107A(A5)\line 001E5000: ADDQ.L  #6,A7\line 001E5002: MOVE.L  582(A5),-(A7)\line 001E5006: MOVE.W  #$000A,-(A7)\line 001E500A:CLR.W\line -(A7)\line 001E500C: MOVE.W  #$7FFF,-(A7)\line 001E5010: SelIText\line 001E5012: CMPI.W  #$0001,`FFFE(A6)\line True if OK was hit\line 001E5018:BNE.S\line ^$001E5020\line \line 001E501A:TST.W\line `FFFC(A6)\line  Unknown: returned value from JSR above\line 001E501E: BEQ.S\line ^$001E4FC0\line 001E5020: CMPI.W  #$0001,`FFFE(A6)\line 001E5026:BNE.S\line ^$001E5070\line \line 001E5028:PEA\line `FF38(A6)\line 001E502C: MOVE.W  #$0006,-(A7)\line 001E5030:JSR\line ^$001E4F58\line \line 001E5034: ADDQ.L  #6,A7\line \line Well, there is a lot of crap here and if you decided to trace the two JSRs you would be in for a long ride.  The first thing to try is to deduce what will happen based on what we already know - we know that if the wrong serial number is entered, the program will go back to ModalDialog to let you change it.  So we need to find a branch that goes back above line 1E4FC0 (the ModalDialog JSR).  If we can find that branch and avoid it, we should be safe.  So we will start tracing down from where the program returned, not making any assumptions yet, but looking at where the branches go.  Right away you will note two JSRs.  Take a look at the parameters passed, and you will note the pair of PEA FEF8(A6) instructions.  So this same piece of information is being passed to both subroutines - nothing to write home about, but interesting.  The real key you should notice here is that there is a TST and BNE after the second subroutine.  This is the first chance the program has to make any decisions (although what decisions we don't know).  Let's assume this branch does not execute (you could assume either way and wind up with the answer) i.e. FFFC(A6) = 0 - some stuff happens that we don't care too much about yet, some text is selected, and the button is tested.  If it was OK, the return value from the second JSR is TSTed and if it was zero (which we are assumming), branch back to 1E4FC0 - back to the ModalDialog JSR.  So this route is incorrect.  Going back, we now need to assume that the branch at line 1E4FF0 did execute.  This time, we jump right to the button check, skip the branch since OK was hit, and again TST the return value from the second JSR.  Since the branch executed, this value cannot be zero, so execution proceeds.  Looking down a few lines we note that there does not seem to be any more branches back to the ModalDialog JSR so we can tentatively assume that this is the end of the protection.\line \line To apply the crack immediately, just make sure that branch executes.  You can do this by typing BRA right over the BNE in TMON.  If, however, you want to make a cracked, unserialized copy (which you can then serialize with anything you like) you need to figure out where code will be in Resedit and change that BNE to BRA.  Unlike the listings I have pasted into this document, TMON will tell you exactly where the code is in the file.  Refer to the above section on TMON MacNosy and Resedit for details, but essentially just find the Code Resource ID # and the offset from the TMON listing.  Then Exit TMON and let Infini-d cancel out.  Next open it the proper code resource in Resedit, scan down to the proper offset, and find the BNE (which is 66 in hex) and change it to BRA (60 in hex).  Save changes and you are set.\line \line FrameMaker 3.0\line \line Serial number dialog scheme again.  This one, however, presents a slight variation - Nosy won't disassemble it properly.  This means that you will have to do all your cracking from within TMON.\line \line Step 1:  Where to start looking.\line \line The only choice we have is to break in via TMON.  The simplest way to do this is to drop into TMON, set a Trace Interrupt for ModalDialog and Exit.  Now launch Framemaker 3.0 and wait for TMON to break in  Here is the code you would see: (note that this listing is from TMON Pro - a TMON 2.8.x listing will be slightly different)\line \line 005B4F88:'CODE'\u174R$0003\u402?$040C+$0284 PEA\line   $01AA(A5)\line 005B4F8C:'CODE'\u174R$0003\u402?$040C+$0288 PEA\line   `FDEC(A6)\line 005B4F90:P 'CODE'\u174R$0003\u402?$040C+$2\u8230? _ModalDialog\line 005B4F92:'CODE'\u174R$0003\u402?$040C+$028E MOVE.W  `FDEC(A6),D0\line 005B4F96:'CODE'\u174R$0003\u402?$040C+$0292 EXT.L\line   D0\line 005B4F98:'CODE'\u174R$0003\u402?$040C+$0294 MOVEQ\line   #$01,D1\line 005B4F9A:'CODE'\u174R$0003\u402?$040C+$0296 CMP.L\line   D0,D1\line 005B4F9C:'CODE'\u174R$0003\u402?$040C+$0298 BNE\line   ^$005B50EA\line       ;'CODE'\u174R$0003\u402?$040C+$3E6\line 005B4FA0:* 'CODE'\u174R$0003\u402?$040C+$2\u8230? CLR.W\line   `FDEC(A6)\line 005B4FA4:'CODE'\u174R$0003\u402?$040C+$02A0 CLR.B\line   (A3)\line 005B4FA6:'CODE'\u174R$0003\u402?$040C+$02A2 TST.L\line   `96FA(A5)\line 005B4FAA:'CODE'\u174R$0003\u402?$040C+$02A6 BEQ.S\line   ^$005B4FC4\line       ;'CODE'\u174R$0003\u402?$040C+$2C0\line 005B4FAC:'CODE'\u174R$0003\u402?$040C+$02A8 MOVE.L  A4,-(A7)\line 005B4FAE:'CODE'\u174R$0003\u402?$040C+$02AA PEA\line   $3802\line           ;$000037D8+$2A\line 005B4FB2:'CODE'\u174R$0003\u402?$040C+$02AE JSR\line   $1702(A5)\line 005B4FB6:'CODE'\u174R$0003\u402?$040C+$02B2 MOVE.L  A3,-(A7)\line 005B4FB8:'CODE'\u174R$0003\u402?$040C+$02B4 MOVE.L  A4,-(A7)\line 005B4FBA:'CODE'\u174R$0003\u402?$040C+$02B6 JSR\line   $419A(A5)\line 005B4FBE:'CODE'\u174R$0003\u402?$040C+$02BA LEA\line   $0010(A7),A7\line 005B4FC2:'CODE'\u174R$0003\u402?$040C+$02BE BRA.S\line   ^$005B4FE8\line       ;'CODE'\u174R$0003\u402?$040C+$2E4\line 005B4FC4:'CODE'\u174R$0003\u402?$040C+$02C0 MOVE.L  `FDE8(A6),-(A7)\line 005B4FC8:'CODE'\u174R$0003\u402?$040C+$02C4 MOVEQ\line   #$05,D0\line 005B4FCA:'CODE'\u174R$0003\u402?$040C+$02C6 MOVE.W  D0,-(A7)\line 005B4FCC:'CODE'\u174R$0003\u402?$040C+$02C8 PEA\line   `FDEE(A6)\line 005B4FD0:'CODE'\u174R$0003\u402?$040C+$02CC PEA\line   `FDF0(A6)\line 005B4FD4:'CODE'\u174R$0003\u402?$040C+$02D0 PEA\line   `FDF4(A6)\line 005B4FD8:'CODE'\u174R$0003\u402?$040C+$02D4 _GetDItem\line 005B4FDA:'CODE'\u174R$0003\u402?$040C+$02D6 TST.L\line   `FDF0(A6)\line 005B4FDE:'CODE'\u174R$0003\u402?$040C+$02DA BEQ.S\line   ^$005B4FE8\line       ;'CODE'\u174R$0003\u402?$040C+$2E4\line 005B4FE0:'CODE'\u174R$0003\u402?$040C+$02DC MOVE.L  `FDF0(A6),-(A7)\line 005B4FE4:'CODE'\u174R$0003\u402?$040C+$02E0 MOVE.L  A3,-(A7)\line 005B4FE6:'CODE'\u174R$0003\u402?$040C+$02E2 _GetIText\line 005B4FE8:'CODE'\u174R$0003\u402?$040C+$02E4 MOVE.L  A3,-(A7)\line 005B4FEA:'CODE'\u174R$0003\u402?$040C+$02E6 JSR\line   ^$005B5670\line       ;'CODE'\u174R$0003\u402?$040C+$96C\line 005B4FEE:'CODE'\u174R$0003\u402?$040C+$02EA TST.L\line   D0\line 005B4FF0:'CODE'\u174R$0003\u402?$040C+$02EC ADDQ.L  #4,A7\line 005B4FF2:'CODE'\u174R$0003\u402?$040C+$02EE BMI\line   ^$005B50C8\line       ;'CODE'\u174R$0003\u402?$040C+$3C4\line 005B4FF6:'CODE'\u174R$0003\u402?$040C+$02F2 CMPI.L  #$00000005,D0\line 005B4FFC:'CODE'\u174R$0003\u402?$040C+$02F8 BGT\line   ^$005B50C8\line       ;'CODE'\u174R$0003\u402?$040C+$3C4\line 005B5000:'CODE'\u174R$0003\u402?$040C+$02FC ADD.L\line   D0,D0\line 005B5002:'CODE'\u174R$0003\u402?$040C+$02FE MOVE.W  ^$005B500A(D0.L),D0\line      ;'CODE'\u174R$0003\u402?$040C+$306\line 005B5006:'CODE'\u174R$0003\u402?$040C+$0302 JMP\line   ^$005B5008(D0.W)\line      ;'CODE'\u174R$0003\u402?$040C+$304\line \line \line If you try to step through this and enter your name etc., you will find that ModalDialog is exiting after any keystroke.  The way to get around this hassle is to get rid of the Trace Interrupt and set a breakpoint after the OK button is hit.  How you ask?  Well, take a look at the code that follows the ModalDialog.  First, D0 gets the dialog item that was modified.  Next D1 gets the value 1 and the two are compared.  From Resedit, you can find the dialog item numbers for all the items and it turns out that item 1 is the OK button, and item 5 is the serial number - these are the two important ones since the program can't proceed until the OK button is hit (we don't care about the cancel button being hit) and then the program must check the serial number.  Fol}